package com.andong.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.andong.domain.dto.UpdatePasswordDTO;
import com.andong.domain.entity.Student;
import com.andong.domain.pojo.PageResult;
import com.andong.domain.pojo.Result;
import com.andong.domain.vo.CoachVO;
import com.andong.mapper.CoachScoreMapper;
import com.andong.utils.*;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.andong.domain.entity.Coach;
import com.andong.service.CoachService;
import com.andong.mapper.CoachMapper;
import com.baomidou.mybatisplus.extension.toolkit.Db;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

import static com.andong.utils.SystemConstant.*;


/**
 * @author 王海云
 * @description 针对表【coach(教练信息表)】的数据库操作Service实现
 * @createDate 2024-01-03 17:57:41
 */
@Service
@Slf4j
public class CoachServiceImpl extends ServiceImpl<CoachMapper, Coach>
        implements CoachService {
    @Resource
    private RedisTemplate<String, Object> redisTemplate;
    @Resource
    private CoachMapper coachMapper;
    @Resource
    private AliOSSUtils aliOSSUtils;
    @Resource
    private AliSMSUtils aliSMSUtils;

    @Resource
    private CoachScoreMapper coachScoreMapper;

    @Override
    public Result selectById(Long id) {
        // 查询身份信息
        Coach coach = lambdaQuery().eq(Coach::getId, id).one();
        CoachVO coachVO = BeanUtil.copyProperties(coach, CoachVO.class);
        coachVO.setScore(coachScoreMapper.getAverage(id));
        Long studentCount = Db.lambdaQuery(Student.class)
                .eq(Student::getCoachId, id)
                .count();
        coachVO.setStudentCount(studentCount);
        return Result.success(coachVO);
    }

    @Override
    public Result updatePasswordByCode(UpdatePasswordDTO dto) throws Exception {
        String phone = dto.getPhone();
        String code = dto.getCode();
        String password = HmacSHA256Utils.calculateHmacSHA256(dto.getPassword());
        Coach coach = getById(dto.getId());
        if (!coach.getPhone().equals(phone)) {
            return Result.error(PHONE_ERROR);
        }
        // 2.从Redis获取缓存的验证码
        String realCode = (String) redisTemplate.opsForValue().get(phone);
        if (!code.equals(realCode)) {
            // 验证码错误 返回错误信息
            return Result.error(CODE_ERROR);
        }
        // 3.验证通过，修改密码
        coach.setPassword(password);
        updateById(coach);
        // 删除缓存的短信验证码
        redisTemplate.delete(phone);
        return Result.success();
    }

    @Override
    public Result updatePasswordByPre(UpdatePasswordDTO dto) throws Exception {
        Long id = dto.getId();
        String prePassword = HmacSHA256Utils.calculateHmacSHA256(dto.getPrePassword());
        String password = HmacSHA256Utils.calculateHmacSHA256(dto.getPassword());
        // 1.从数据库获取学员信息
        Coach coach = lambdaQuery().eq(Coach::getId, id).one();
        // 2.判断原密码是否正确
        if (!coach.getPassword().equals(prePassword)) {
            return Result.error(PRE_PASSWORD_ERROR);
        }
        // 3.更新密码
        coach.setPassword(password);
        updateById(coach);
        return Result.success();
    }

    @Override
    public PageResult queryList(Integer page, Integer pageSize, String name, Integer gender, Integer licenseType, LocalDate begin, LocalDate end) {
        // 构造Coach分页器
        Page<Coach> coachPage = new Page<>(page, pageSize);
        // 获取当前访客身份和id
        String identity = (String) BaseContext.getCurrentIdAndIdentity().get(CURRENT_IDENTITY);
        Student student;
        Integer studentLicenseType = null;
        if (STUDENT.equals(identity)) {
            Long id = (Long) BaseContext.getCurrentIdAndIdentity().get(CURRENT_ID);
            // 查询学员驾照类型
            student = Db.lambdaQuery(Student.class)
                    .eq(Student::getId, id)
                    .one();
            studentLicenseType = student.getLicenseType();
        }
        // 构造Coach条件查询器, 得到Coach分页查询基本信息结果
        coachPage = lambdaQuery()
                .like(name != null, Coach::getName, name)
                .eq(STUDENT.equals(identity), Coach::getLicenseType, studentLicenseType)
                .eq(gender != null, Coach::getGender, gender)
                .eq(licenseType != null, Coach::getLicenseType, licenseType)
                .ge(begin != null, Coach::getCreateTime, begin)
                .le(end != null, Coach::getCreateTime, end)
                .orderByDesc(Coach::getUpdateTime)
                .page(coachPage);
        // 使用stream流的方式对记录中的每一条数据进行处理
        List<Coach> records = coachPage.getRecords();
        List<CoachVO> voList = records.stream().map(recode -> {
            CoachVO coachVO = new CoachVO();
            coachVO.setScore(coachScoreMapper.getAverage(recode.getId()));
            Long count = Db.lambdaQuery(Student.class)
                    .eq(Student::getCoachId, recode.getId())
                    .count();
            coachVO.setStudentCount(count);
            Long count2 = Db.lambdaQuery(Student.class)
                    .eq(Student::getCoachId, recode.getId())
                    .ne(Student::getStage, 5)
                    .count();
            coachVO.setStudentOnCount(count2);
            BeanUtil.copyProperties(recode, coachVO);
            return coachVO;
        }).toList();
        return new PageResult(coachPage.getTotal(), voList);
    }

    @Override
    public void updateImage(String url) {
        // 获取当前用户id
        Long id = (Long) BaseContext.getCurrentIdAndIdentity().get(CURRENT_ID);
        // 获取原图片URL地址
        Coach coach = coachMapper.selectById(id);
        String originalUrl = coach.getImage();
        // 更新图片
        coach.setImage(url);
        updateById(coach);
        if (Objects.nonNull(originalUrl)) {
            // 删除原图片
            aliOSSUtils.delete(originalUrl);
        }
    }

    @Override
    public Result updatePhone(String phone, String code) {
        Long id = (Long) BaseContext.getCurrentIdAndIdentity().get(0);
        // 1.校验验证码
        if (!aliSMSUtils.checkCode(phone, code)) {
            return Result.error(CODE_ERROR);
        }
        // 2.更新手机号
        lambdaUpdate()
                .eq(Coach::getId, id)
                .set(Coach::getPhone, phone)
                .update(getById(id));
        return Result.success();
    }

    @Override
    public Result updateStatus(Long id, Integer status) {
        // 检查参数格式
        if (!ALL_ACCOUNT_STATUS.contains(status)) {
            return Result.error(STATUS_ERROR);
        }
        lambdaUpdate()
                .eq(Coach::getId, id)
                .set(Coach::getStatus, status)
                .update(getById(id));
        // 更新缓存
        redisTemplate.opsForValue().set(ACCOUNT_STATUS + STUDENT + id, status, ACCOUNT_STATUS_EXPIRE, TimeUnit.MINUTES);
        return Result.success();
    }

    @Override
    public Result delete(Long id) {
        // 查找名下是否有未毕业学员
        Long count = Db.lambdaQuery(Student.class)
                .eq(Student::getCoachId, id)
                .ne(Student::getStage, FINISH)
                .count();
        if (count != ZERO) {
            return Result.error(COACH_HAS_STUDENT);
        }
        // 删除阿里云OSS图片
        aliOSSUtils.delete(getById(id).getImage());
        aliOSSUtils.delete(getById(id).getLicenseImage());
        // 删除教练信息
        removeById(id);
        // 删除账号状态缓存
        redisTemplate.delete(ACCOUNT_STATUS + COACH + id);
        return Result.success();
    }

    @Override
    public Result insert(Coach coach) throws Exception {
        String username = coach.getUsername();
        String idNumber = coach.getIdNumber();
        // 4.设置默认密码并加密存储
        coach.setPassword(HmacSHA256Utils.calculateHmacSHA256(CommonUtils.getDefaultPassword(idNumber)));
        // 5.设置性别
        coach.setGender(CommonUtils.getGender(idNumber));
        // 6.设置年龄
        coach.setAge(CommonUtils.getAge(idNumber));
        // 7.设置默认状态
        coach.setStatus(ACCOUNT_NORMAL_CODE);
        save(coach);
        return Result.success();
    }
}




